# encoding: utf-8
# Author    : limusen
# Datetime  : 2023/9/27 09:51
# File      : base.py
# explain   : 文件说明

import os
import time
import base64
import json
import ddddocr
import requests
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium import webdriver
from common.browse import Browser
from common.config import local_config
from common.logs import logger


class Base:
    code_path = os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))), local_config.code_path)
    ocr = ddddocr.DdddOcr()

    def __init__(self, driver):
        self.driver = driver
        self.host = local_config.host

    def open_url(self, url):
        self.driver.get(self.host + url)
        logger.info("打开url: {}".format(url))

    def wait(self, data=3):
        time.sleep(data)

    def close(self):
        self.driver.close()
        logger.info("关闭当前tab标签")

    def quit(self):
        self.driver.quit()
        logger.info("退出浏览器")

    def get_element(self, locator):
        try:
            # 使用匿名函数传入显示等待当中
            element = WebDriverWait(self.driver, 20, 0.5).until(
                lambda x: x.find_element(*locator))
        except Exception as e:
            logger.error("元素不能识别,原因是: %s" % e.__str__())
            raise
        return element

    def click(self, locator):
        try:
            self.get_element(locator).click()
        except Exception as e:
            # 输入到日志
            logger.error("点击操作失败！原因是：[{}]".format(e.__str__()))

    def send_keys(self, locator, text):
        try:
            self.get_element(locator).send_keys(text)
        except Exception as e:
            # 输入到日志
            logger.error("输入操作失败！原因是：[{}]".format(e.__str__()))

    def input_clear(self, locator):
        """
        清除文本内容
        :param locator:
        :return:
        """
        try:
            self.get_element(locator).clear()
        except Exception as e:
            # 输入到日志
            logger.error("清除文本，操作失败！原因是：[{}]".format(e.__str__()))

    def get_attribute(self, locator, attr):
        """
        获取文本属性
        :param locator:
        :param attr:
        :return:
        """
        try:
            self.wait()
            message = self.get_element(locator).get_attribute(attr)
            return message
        except Exception as e:
            # 输入到日志
            logger.error("获取文本属性，操作失败！原因是：[{}]".format(e.__str__()))

    def exit_driver(self):
        self.driver.quit()
        logger.info("退出浏览器")

    def back_up(self):
        self.driver.back()
        logger.info("返回上一页")

    def forward(self):
        self.driver.forward()
        logger.info("前进一页")

    def set_window_max(self):
        self.driver.maximize_window()
        logger.info("浏览器最大化")

    def page_refresh(self):
        self.driver.refresh()
        logger.info("浏览器刷新")

    def get_title(self):
        value = self.driver.title
        logger.info("获取标题：%s" % value)
        return value

    def get_url(self):
        value = self.driver.current_url
        logger.info("获取url：%s" % value)
        return value

    def get_page_source(self):
        """
        获取当前页面源码
        :return:
        """
        source = self.driver.page_source
        logger.info("获取页面源码...")
        return source

    def get_text(self, locator):
        """
        获取元素文本信息
        :param locator:
        :return:
        """
        text = self.get_element(locator).text
        logger.info('获取文本信息：%s' % text)
        return text

    def get_page_img(self, locator=None, name=None):
        """
        截图获取当前页面信息
        :return:
        """
        current_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
        current_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
        if name:
            screenshot_path = os.path.join(current_path, local_config.screen_shot_path, f"{name}.png")
        else:
            screenshot_path = os.path.join(current_path, local_config.screen_shot_path, f"{current_time}.png")

        if locator:
            result = self.get_element(locator)
            result.screenshot(screenshot_path)
            self.wait(2)
            logger.info("指定元素截图")
        else:
            self.driver.save_screenshot(screenshot_path)

    def get_window_handle(self):
        """
        获取所有句柄
        :return:
        """
        return self.driver.window_handles

    def switch_windows(self, name="new"):
        """
        :param name: 默认跳转到新页面
        :return:
        """
        # 等待 -- 获取句柄 -- 切换句柄
        self.wait(1)
        if name == "new":
            self.driver.switch_to.window(self.get_window_handle()[-1])

    def switch_to_iframe(self, locator):
        self.wait(1)
        try:
            ele = self.get_element(locator)
            self.driver.switch_to.frame(ele)
        except Exception as e:
            # 输入到日志
            logger.error("点击操作失败！原因是：[{}]".format(e.__str__()))
            # 截图
            self.get_page_img()
            raise
        else:
            logger.info("现在跳转框架!")

    def switch_to_default(self):
        """
        跳转回原来的框架
        :return:
        """
        try:
            self.wait(1)
            self.driver.switch_to.default_content()
        except Exception as e:
            # 输入到日志
            logger.error("点击操作失败！原因是：[{}]".format(e.__str__()))
            # 截图
            self.get_page_img()
            raise
        else:
            logger.info("跳回原来框架")

    def check_element_exists(self, locator):
        """
        判断元素是否存在，存在则返回true，不存在返回false
        :param element:
        :param condition:
        :return:
        """
        try:
            self.get_element(locator)
            logger.info('当前元素存在')
            return True
        except Exception as e:
            logger.error("当前元素不存在，报错啦~~~")
            return False

    def save_code_png(self, locator, attr, photo_name='code'):
        """
        保存验证码信息到本地，该方法需要从元素上直接获取到base64的值才能使用
        :param locator:
        :return:
        """
        try:
            # 下载验证码为base64文件并保存
            screen_save_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
                                            local_config.screen_shot_path, '{}.png'.format(photo_name))

            # 将图片保存到本地
            file_fragment = self.get_attribute(locator, attr)

            if type(file_fragment) == None:
                logger.error('未获取到具体的attr值')
                return

            file_fragment_01 = file_fragment.split(',')[1]
            img_data = base64.b64decode(file_fragment_01)
            file = open(screen_save_path, 'wb')
            file.write(img_data)
            file.close()

            # 破解验证码
            ocr = ddddocr.DdddOcr()
            screen_save_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
                                            local_config.screen_shot_path, 'code.png')
            with open(screen_save_path, 'rb') as pf:
                img_bytes = pf.read()
            code = ocr.classification(img_bytes)
        except Exception as e:
            # 输入到日志
            logger.error("页面操作失败！原因是：[{}]".format(e.__str__()))
            # 截图
            self.get_page_img()
            raise

        return code

    def ImageRecognition(self, path=code_path):
        """
        识别验证码方法
        :param path: 验证码地址
        :return: 识别完成的验证码
        """
        try:
            with open(path, 'rb') as pf:
                img_bytes = pf.read()
                pf.close()

            result = Base.ocr.classification(img_bytes)
            logger.debug("获取验证码成功： %s" % result)
            return result

        except Exception as e:
            logger.error(e.__str__())
            return e.__str__()

    def request(self, method, url, payload=None, headers=None, **kwargs):
        if method == "get":
            resp = requests.get(self.host + url, params=payload, headers=headers, **kwargs)
        else:
            resp = requests.post(self.host + url, json=payload, headers=headers, **kwargs)
        assert resp.status_code == 200, self.host + url + "接口访问异常"
        return resp


if __name__ == '__main__':
    driver = Browser().get_driver()
    bs = Base(driver)
    print(bs.ImageRecognition())
    bs.open_url('simple/reg')
    time.sleep(2)
    bs.get_page_img((By.XPATH, '//*[@id="captchaImg"]'), 'code')
    result = bs.ImageRecognition()
    time.sleep(2)
    print(result)
    bs.close()
